package com.bsi.sentinel.rest.controller;

import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @ClassName RestController
 * @Author LiuSong
 * @Date 2020/7/30 15:58
 * @Version 1.0
 * @Description sentinel与restTemplate搭配使用
 */
@RequestMapping("/rest")
@RestController
public class RestSentinelController {

    // 这段代码放在启动类中
    //fallback:对应异常熔断降级方法
    //block：对应限流熔断降级方法
    @Bean
    @LoadBalanced
    @SentinelRestTemplate(fallbackClass = RestFallBack.class, fallback = "doFallBack",
            blockHandler = "doBlock", blockHandlerClass = RestFallBack.class)
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    // 放在controller中
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/demoRest")
    public String demoRest() {
        MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<String, String>();
        paramMap.add("demo", "sentinel");
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>();
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("http://demo-service/sentinel/demo", httpEntity, String.class);
        return stringResponseEntity.getBody();
    }


    public static class RestFallBack {
        public static SentinelClientHttpResponse doBlock(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
            System.err.println("Oops: " + ex.getClass().getCanonicalName());
            return new SentinelClientHttpResponse("限流熔断降级");
        }

        public static SentinelClientHttpResponse doFallBack(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
            System.err.println("fallback: " + ex.getClass().getCanonicalName());
            return new SentinelClientHttpResponse("异常熔断降级");
        }
    }
}
